#include <unistd.h>
#include "global.h"
#include "threadpool.h"
#include "memorypool.h"

//静态成员初始化
pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER;
bool CThreadPool::m_shutdown = false;

CThreadPool::CThreadPool()
{
    m_iRunningThreadNum = 0;
    m_iLastEmgTime = 0;
    m_iPrintInfoTime = 0;
    m_iCurTime = 0;
}

CThreadPool::~CThreadPool()
{
    //资源释放统一在StopAll()中进行
}

bool CThreadPool::Create(int thread_num)
{
    ThreadItem* pnew; //线程结构体指针
    int err; //记录错误码

    for (int i = 0; i < m_iThreadNum; ++i)
    {
        m_threadVector.push_back(pnew = new ThreadItem(this)); //初始化线程结构体传入线程池this指针
        err = pthread_create(&pnew->_Handle, nullptr, ThreadFunc, pnew);
        if (err != 0)
        {
            LOGSTDERR(err, "CThreadPool::Create() failed");
            return false;
        }

        LOGSTDERR(0, "CThreadPool::Create() success");
    }

checkAlive:
    for (auto it = m_threadVector.begin(); it != m_threadVector.end(); ++it)
    {
        if ((*it)->isRunning) continue;
        usleep(100 * 1000); //单位是us微妙，就是休眠100ms保证线程都起来
        goto checkAlive;
    }

    return true; //确保所有线程都正常启动之后，才能返回true
}

void* CThreadPool::ThreadFunc(void* threadData)
{
    ThreadItem* pThread = static_cast<ThreadItem *>(threadData); //将传入的this指针转为ThreadItem指针，因为这个函数是静态成员函数，是不含有this指针的
    CThreadPool* pThreadPoolObj = pThread->_pThis; //指向线程池对象的指针，方便使用线程池的管理函数对线程进行操作

    char *jobinfo = nullptr; //用于获取接受Out消息队列的信息，数据包等
    CMemory* pMemory = CMemory::GetInstance();
    int err; //记录错误码

    pthread_t tid = pthread_self(); //获取自身线程ID，方便输出日志调试
    while (true)
    {
        err = pthread_mutex_lock(&m_pthreadMutex);
        if (err != 0)
        {
            LOGSTDERR(err, "CThreadPool::ThreadFunc() pthread_mutex_lock() error");
        }

        while( (jobinfo = g_Socket.outMsgRecvQueue()) == nullptr && m_shutdown == false ) //利用while防止惊群
        {
            if (pThread->isRunning == false)
            {
                pThread->isRunning = true; //执行到这里，线程才算是启动成功了
            }

            pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex); //所有线程在此等待唤醒
        }

        jobinfo = g_Socket.outMsgRecvQueue();
        if (jobinfo == nullptr && m_shutdown == false)
        {
            LOGSTDERR(0, "start working on sth...");
        }

        err = pthread_mutex_unlock(&m_pthreadMutex);
        if (err != 0)
        {
            LOGSTDERR(err, "CThreadPool::ThreadFunc() pthread_mutex_unlock() error");
        }

        if (m_shutdown)
        {
            if (jobinfo != nullptr)
            {
                pMemory->FreeMemory(jobinfo);
            }
            break; //线程退出
        }

        //至此，可以处理数据了
        ++pThreadPoolObj->m_iRunningThreadNum;
        g_Socket.threadRecvProcFunc(jobinfo); //处理消息队列中来的消息
        sleep(5); //假装在忙碌地干活
        pMemory->FreeMemory(jobinfo);
        --pThreadPoolObj->m_iRunningThreadNum;
    }

    return (void*)0;
}

void CThreadPool::StopAll()
{
    if (m_shutdown == true) //如果停止标记已经是true了就不用往下执行了
    {
        return ;
    }
    m_shutdown = true;
    int err = pthread_cond_broadcast(&m_pthreadCond); //唤醒所有线程，准备退出
    if (err != 0)
    {
        LOGSTDERR(err, "CThreadPool::StopAll() pthread_cond_broadcast() error");
    }

    //等待所有线程返回
    //std::vector<ThreadItem *>::iterator it;
    for (auto it = m_threadVector.begin(); it != m_threadVector.end(); ++it)
    {
        pthread_join((*it)->_Handle, nullptr);
    }

    pthread_mutex_destroy(&m_pthreadMutex);
    pthread_cond_destroy(&m_pthreadCond);

    for (auto it = m_threadVector.begin(); it != m_threadVector.end(); ++it)
    {
        if (*it) delete *it;
    }
    m_threadVector.clear();
    LOGSTDERR(0, "CThreadPool::StopAll() success, all threads in threadpool terminated");
    return ;
}

void CThreadPool::Call(int recvMsgQueueCnt)
{
    int err = pthread_cond_signal(&m_pthreadCond);
    if (err != 0)
    {
        LOGSTDERR(err, "CThreadPool::Call() pthread_cond_signal() error");
    }

    if (m_iThreadNum == m_iRunningThreadNum)
    {
        time_t curTime = time(nullptr);
        if (curTime - m_iLastEmgTime > 0)
        {
            m_iLastEmgTime = curTime; //更新上次除法异常情况（空闲线程不足）的时间
            LOGSTDERR(0, "CThreadPool::Call() not enough threads available");
        }
    }

    //TODO:干活代码

    return ;
}